#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <thread>
#include <sys/socket.h>
#include <opencv2/opencv.hpp>
#include "detect_server.h"
#include "main.h"
#include "videoio_server.h"

using namespace cv;
const char* dst = "../data/infrared_640dst.jpg"; //坑 这里的路径不是.cpp的相对路径 是可执行文件的相对路径

const char *model_path = "../model/yolov5_fsmvocs.rknn";
char *device_id = (char*)"8b1b18fdd0f2688c"; //zhou
// char *device_id = (char*)"e84ffc9122c075b8"; //zhang
const int thread_num = 6;
const int NPU_threads = 4;
int NPU_ready = 0;
int NPU_finish = 0;

// 各任务进行状态序号
int idxInputImage = 0;  // image index of input video
int idxOutputImage = 0; // next frame index to be output 保证queueOutput_server序号正确
bool bReading = true;   // flag of input

// 多线程控制相关
mutex mtxQueueInput_server;					  // mutex of input queue server 
mutex mtxQueueOutput_server;    		  // mutex of display queue
queue<pair<int, Mat>> queueInput_server;  // input queue server 
queue<det_res> queueOutput_server;  	  // output queue 目标检测输出队列

// 文件路径
const char* SAVE_PATH = "../res/Track_res.mp4";

void error_handling(const char *message);

int main(int argc, char *argv[])
{
	int sock_tcp;
	int clnt_sock;

	struct sockaddr_in serv_addr;
	struct sockaddr_in clnttcp_addr;
	socklen_t clnt_addr_size;

	char message[]="Hello World!";
	
	if(argc!=2){
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}
	
	sock_tcp=socket(PF_INET, SOCK_STREAM, 0);
	if(sock_tcp == -1)
		error_handling("socket() error");
	
	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_addr.sin_port=htons(atoi(argv[1]));
	
	if(bind(sock_tcp, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1 )
		error_handling("bind() error"); 
	
	if(listen(sock_tcp, 5)==-1)
		error_handling("listen() error");
	
	clnt_addr_size=sizeof(clnttcp_addr);  
	sock_tcp=accept(sock_tcp, (struct sockaddr*)&clnttcp_addr,&clnt_addr_size);
	if(sock_tcp==-1)
		error_handling("accept() error");  
	
    //-------------------------------TCP建立连接-----------------------------------
	
	array<thread, thread_num> threads;
	threads = {
					//只使用一个的进程 传入cpu_id
					thread(videoTransServer, 5, sock_tcp),
					thread(send_dets, 4, sock_tcp),
					thread(detect_process, model_path, 0, device_id, sock_tcp),
					thread(detect_process, model_path, 1, device_id, sock_tcp),
					thread(detect_process, model_path, 2, device_id, sock_tcp),
					thread(detect_process, model_path, 3, device_id, sock_tcp),
				};
	for (int i = 0; i < thread_num; i++)
		threads[i].join();
	
	close(clnt_sock);	
	close(sock_tcp);
	return 0;
}

void error_handling(const char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}